<?php

namespace App\Http\Controllers\Port;

use App\Models\UserInfo;
use App\Models\UserWechatInfo;
use App\Validate\WechatAuthValidate;
use Exception;
use Illuminate\Support\Facades\Cache;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Log;

/**
 * 微信授权登录   wx端
 * Class auth
 * @package app\Port\controller
 */
class WechatAuthController extends CommonController
{
    private $appid;
    private $appsecret;
    private $applet_appid;
    private $applet_appsecret;


    public $model = null;
    public $validate = null;

    public function __construct()
    {
        parent::__construct();
        $this->appid = config('other.web_appid');
        $this->appsecret = config('other.web_appsecret');
        $this->applet_appid = config('other.applet_appid');
        $this->applet_appsecret = config('other.applet_appsecret');

        $this->model = new UserWechatInfo();
        $this->validate = new WechatAuthValidate();
    }

    /**
     * 微信确认授权后登录（小程序使用）
     * @param code  微信code参数
     * @param invite  邀请码
     * @param nickname 用户昵称
     * @param head_img 用户头像  （新注册微信，无头像）
     */
    public function appletIndexInfo()
    {
        //增加验证场景进行验证
        if (!$this->validate->scene('wx_auth')->check($this->request->all())) {
            return $this->returnApi(201,  $this->validate->getError());
        }

        $code = $this->request->code;/*code参数*/
        $invite = $this->request->invite;/*code参数*/
        $nickname = $this->request->nickname;
        $head_img = $this->request->head_img ? $this->request->head_img : ($this->getImgAddrUrl() . 'default/default_head_img.png');

        $arr = $this->getSmallOpenId($code);
        if (empty($arr['open_id'])) {
            return $this->returnApi(202, '授权失败，请联系管理员处理！');
        }
        $session_key = $arr['session_key'];
        $openid = $arr['open_id'];

        // 启动事务
        DB::beginTransaction();
        try {
            /*检查是否已经绑定过账号*/
            $wechat = $this->model->change([
                'nickname' => $nickname,
                'head_img' => $head_img,
                'session_key' => $session_key,
                'open_id' => $openid,
            ]);
            if (empty($wechat['token'])) {
                throw new Exception('登录失败');
            }

            //邀请人加积分
            if (config('other.is_need_score') && $wechat['is_add'] && !empty($invite)) {
                /**执行积分规则 */
                //增加邀请人的积分
                $userInfoModel = new UserInfo();
                $invite_user_info = $userInfoModel->where('qr_code', $invite)->first();
                if (!empty($invite_user_info['account_id'])) {
                    //添加邀请人数
                    $invite_user_info->invite_number = ++$invite_user_info->invite_number;
                    $invite_user_info->save();

                    $scoreRuleObj = new \App\Http\Controllers\ScoreRuleController();
                    $score_status = $scoreRuleObj->checkScoreStatus(2, $invite_user_info['id'], $invite_user_info['account_id']);

                    if ($score_status['code'] == 200) {
                        $system_id = $this->systemAdd($score_status['score_info']['type_name'], $invite_user_info['id'], $invite_user_info['account_id'], 11, 0, $score_status['score_info']['intro']);

                        $scoreRuleObj->scoreChange($score_status, $invite_user_info['id'], $invite_user_info['account_id'], $system_id); //添加积分消息
                    }
                }

                //写入用户信息表
                $userInfoModel->where('wechat_id', $wechat['wechat_id'])->update([
                    'invite_user_id' => !empty($invite_user_info['id']) ? $invite_user_info['id'] : 0,
                    'invite_account_id' => !empty($invite_user_info['account_id']) ? $invite_user_info['account_id'] : 0,
                ]);
            }

            $userInfoModel = new UserInfo();
            $account_info = $userInfoModel->getAccountInfo($wechat['token']);
            if ($account_info) {
                $account = $account_info['account'];
            } else {
                $account = null;
            }

            DB::commit();
            return $this->returnApi(200, "授权成功", true, ['token' => $wechat['token'], 'qr_code' => $wechat['qr_code'], 'account' => $account, 'head_img' => $head_img, 'nickname' => $nickname]);
        } catch (\Exception $e) {
            // 回滚事务
            DB::rollBack();
            return $this->returnApi(202, '授权信息保存失败');
        }
    }


    /**
     * 微信确认登陆后接受,获取信息  (微信公众号使用)
     * @param code  微信code参数
     * @param invite  邀请码
     */
    public function indexInfo()
    {
        $appid = $this->appid;
        $appsecret = $this->appsecret;

        $code = $this->request->code;/*code参数*/
        $invite = $this->request->invite;/*invite参数*/

        if (empty($code)) {
            return $this->returnApi(201, "参数传递错误");
        }
        /*换取 access_token*/
        $json = request_url('https://api.weixin.qq.com/sns/oauth2/access_token?appid=' . $appid . '&secret=' . $appsecret . '&code=' . $code . '&grant_type=authorization_code');

        $arr = json_decode($json, true); //转化为数组

        if (empty($arr['access_token'])) {
            Log::error('授权失败，请联系管理员处理！' . date('Y-m-d H:i:s'));
            Log::error($arr);

            return $this->returnApi(202, '授权失败，请联系管理员处理！');
        }

        $access_token = $arr['access_token'];
        $openid = $arr['openid'];

        /*传入token和openid 返回用户的信息*/
        $info_url = 'https://api.weixin.qq.com/sns/userinfo?access_token=' . $access_token . '&openid=' . $openid . '⟨=zh_CN';
        $info = request_url($info_url);
        $info = json_decode($info, true);

        if (config('other.is_web_auth') && !isset($info['unionid'])) {
            return $this->returnApi(202, '授权信息获取失败，请检查微信开放平台配置！');
        }
        //web端登录多了一个  unionid
        if (isset($info['nickname']) && isset($info['headimgurl'])) {
            // 启动事务
            DB::beginTransaction();
            try {
                /*检查是否已经绑定过账号*/
                $wechat = $this->model->change([
                    'union_id' => !empty($info['unionid']) ? $info['unionid'] : '',
                    'nickname' => $info['nickname'],
                    'head_img' => $info['headimgurl'],
                    'open_id' => $openid,
                    'source' => 2,
                ]);

                if (empty($wechat['token'])) {
                    throw new Exception('登录失败');
                }

                //邀请人加积分
                if (config('other.is_need_score') && $wechat['is_add'] && !empty($invite)) {
                    /**执行积分规则 */
                    //增加邀请人的积分
                    $userInfoModel = new UserInfo();
                    $invite_user_info = $userInfoModel->where('qr_code', $invite)->first();
                    if (!empty($invite_user_info['account_id'])) {
                        //添加邀请人数
                        $invite_user_info->invite_number = ++$invite_user_info->invite_number;
                        $invite_user_info->save();

                        $scoreRuleObj = new \App\Http\Controllers\ScoreRuleController();
                        $score_status = $scoreRuleObj->checkScoreStatus(2, $invite_user_info['id'], $invite_user_info['account_id']);

                        if ($score_status['code'] == 200) {
                            $system_id = $this->systemAdd($score_status['score_info']['type_name'], $invite_user_info['id'], $invite_user_info['account_id'], 11, 0, $score_status['score_info']['intro']);

                            $scoreRuleObj->scoreChange($score_status, $invite_user_info['id'], $invite_user_info['account_id'], $system_id); //添加积分消息
                        }
                    }

                    //写入用户信息表
                    $userInfoModel->where('wechat_id', $wechat['wechat_id'])->update([
                        'invite_user_id' => !empty($invite_user_info['id']) ? $invite_user_info['id'] : 0,
                        'invite_account_id' => !empty($invite_user_info['account_id']) ? $invite_user_info['account_id'] : 0,
                    ]);
                }

                $userInfoModel = new UserInfo();
                $account_info = $userInfoModel->getAccountInfo($wechat['token']);
                if ($account_info) {
                    $account = $account_info['account'];
                } else {
                    $account = null;
                }

                DB::commit();
                return $this->returnApi(200, "授权成功", true, ['token' => $wechat['token'], 'qr_code' => $wechat['qr_code'], 'account' => $account, 'head_img' => $info['headimgurl'], 'nickname' => $info['nickname']]);
            } catch (\Exception $e) {
                Log::error($e->getMessage().$e->getFile().$e->getLine());
                // 回滚事务
                DB::rollBack();
                return $this->returnApi(202, '授权信息保存失败');
            }
        }

        return $this->returnApi(202, '授权信息保存失败');
    }



    /**
     * 根据code获取小程序用户 openid   （内部调用）
     * @param code
     **/
    public function getSmallOpenId($code)
    {
        if (empty($code)) {
            return false;
        }
        //小程序授权地址
        $json = request_url('https://api.weixin.qq.com/sns/jscode2session?appid=' . $this->applet_appid . '&secret=' . $this->applet_appsecret . '&js_code=' . $code . '&grant_type=authorization_code');
        $arr = json_decode($json, true); //转化为数组

        if (isset($arr['openid'])) {
            $openid = $arr['openid'];
            $session_key = $arr['session_key'];
            return ['open_id' => $openid, 'session_key' => $session_key];
        } else {
            Log::error('授权失败：' . $json);
        }
        return false;
    }

    /**
     * 获取小程序 access_token
     * @param $contractor YXYZ
     */
    public function getWxAppletAccessToken()
    {
        $key = 'wx_applet_access_token';
        $access_token = Cache::get($key);

        //获取appid  和 appsecret
        if (empty($access_token)) {
            $url = 'https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=' . $this->appid . '&secret=' . $this->appsecret;
            $json = request_url($url);
            $res = json_decode($json, true);

            if (!isset($res['access_token'])) {
                Log::error('获取access_token失败：' . $json);
            }

            Cache::put($key, $res['access_token'], $res['expires_in']);

            $access_token = $res['access_token'];
        }
        return $access_token;
    }
}
